import wx
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
from dragdrop import listDrop
import cPickle
import wx.lib.delayedresult as delayedResult
import menus, format, local, time, locale

class extListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
	ignoreListEvents = False

	def __init__(self, parent, size, style, hdlPanel):
		wx.ListCtrl.__init__(self, parent=parent, size=size, style=style)
		ListCtrlAutoWidthMixin.__init__(self)
		self.parent = hdlPanel
		self.frame = hdlPanel.hdlFrame
		dt = listDrop(self.parent, self)
		self.SetDropTarget(dt)
		
		if self.parent.hdlFrame.autoFocus:
			self.Bind(wx.EVT_ENTER_WINDOW, self.onEnter)
			
		self.blLocal = hdlPanel.blLocal

		self.SetImageList(self.parent.iconPackage.imageList, wx.IMAGE_LIST_SMALL)
		self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.onBeginEdit)
		self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.onEndEdit)
		self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.onRightClick)
		self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
		
	def getItemInfo(self, idx):
		"""Collect all relevant data of a listitem, and put it in a list"""
		l = []
		l.append(self.GetItemText(idx)) # Text first column
		l.append(idx) # We need the original index, so it is easier to eventualy delete it
		l.append(self.GetItemData(idx)) # Itemdata
		for i in range(1, self.GetColumnCount()): # Possible extra columns
				l.append(self.GetItem(idx, i).GetText())
		return l
		
	def startDrag(self, e):
		# Put together a data object for drag-and-drop from this list.
		l = []
		l.append((self.Label, self.blLocal))
		idx = -1
		while True: # find all the selected items and put them in a list
			idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
			if (idx == -1):
					break
			l.append(self.getItemInfo(idx))

		# Pickle the items list.
		itemdata = cPickle.dumps(l, 1)
		# create our own data format and use it in a
		# custom data object
		ldata = wx.CustomDataObject('ListCtrlItems')
		ldata.SetData(itemdata)
		# Now make a data object for the  item list.
		data = wx.DataObjectComposite()
		data.Add(ldata)

		# Create drop source and begin drag-and-drop.
		dropSource = wx.DropSource(self)
		dropSource.SetData(data)
		res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
		
	def setBackColours(self):
		for x in range(0, self.GetItemCount(), 2):
			self.SetItemBackgroundColour(x, '#ecf3fe')
		
	def onBeginEdit(self, event):
		self.ignoreListEvents = True
		if self.blLocal:
			if self.frame.blWin and self.Number == 1:
				event.Veto()
				return
			self.strName = self.Label + '/' + event.GetText()
		else:
			realName = self.frame.dirList.getReals(self.Label + '/' + event.GetText())
			self.strName = self.Label + '/' + realName
		
	def onEndEdit(self, event):
		if not event.IsEditCancelled():
			newText = event.GetText()
			strNew = self.Label + '/' + newText
			try:
				if self.blLocal:
					os.rename(self.strName, strNew)
				else:
					self.frame.mFTP.renameFile(self.Label, self.strName, strNew, self.Number)
				
				self.parent.lblName.SetLabel(newText)
			except:
				print('Failed to rename file')
				event.Veto()
		
		self.ignoreListEvents = False
	
	def onRightClick(self, event):
		sel = self.getSelections()
		ls = len(sel)

		if ls < 2:
			self.Select(sel[0], 1)

		self.frame.PopupMenu(menus.contextMenu(self, self.frame, self.blLocal))
		
	def onEnter(self, event):
		hdl = self.parent.hdlFrame
		obj = hdl.FindFocus()
		blText = obj == hdl.txtHost or obj == hdl.txtUser\
			or obj == hdl.txtPassword or obj == hdl.txtFilter

		if hdl.IsActive() and not(blText) and not(self.ignoreListEvents):
			event.GetEventObject().SetFocus()

	def selectAll(self, event):
		self.ignoreListEvents = True
		for x in range(0, self.GetItemCount()):
			self.Select(x, 1)
		self.ignoreListEvents = False
		
		self.parent.getGenericInfo(self, self.blLocal)
			
	def getStrings(self):
		lstItems = []
		endPos = self.GetItemCount()
		for x in range(0, endPos):
			lstItems.append(self.GetItemText(x))

		return lstItems

	def setSelection(self, lngItem):
		lstItems = []
		endPos = self.GetItemCount()
		for x in range(0, endPos):
			self.Select(x, 0)
			
		self.Select(lngItem, 1)

	def getSelections(self):
		lstItems = []
		endPos = self.GetSelectedItemCount()
		startPos = -1
		for x in range(-1, endPos - 1):
			y = self.GetNextItem(startPos, state= wx.LIST_STATE_SELECTED)
			lstItems.append(y)
			startPos = y

		return lstItems
		
class previewWindow(wx.Frame):
	def __init__(self, bmp, pwf='Preview'):
		self.bmp = bmp
		self.pwf = pwf
		self.title = format.getNameFromPath(pwf)
		wx.Frame.__init__(self, None, -1, title=self.title, style=wx.DEFAULT_FRAME_STYLE)
		if bmp:			
			sizer = wx.BoxSizer(wx.VERTICAL)
			
			self.swWindow = wx.ScrolledWindow(self, style=wx.FULL_REPAINT_ON_RESIZE)
			self.swWindow.SetBackgroundColour((0,0,0))
			self.swWindow.SetScrollbars(1,1,1,1)

			sizer.Add(self.swWindow, 1, wx.EXPAND)
			self.SetSizer(sizer)
			
			self.sbImage = wx.StaticBitmap(self.swWindow)
			self.sbImage.Bind(wx.EVT_MOUSE_EVENTS, self.onSbImageMouse)
			sizerScroll = wx.BoxSizer(wx.VERTICAL)
			sizerScroll.Add(self.sbImage, 1, wx.EXPAND | wx.ALIGN_CENTER)
			
			mnuRight = wx.Menu()
			mnuZoomIn = mnuRight.Append(-1, 'Zoom &In\tZ')
			mnuZoomOut = mnuRight.Append(-1, 'Zoom &Out\tX')
			mnuActualSize = mnuRight.Append(-1, '&Actual Size\tA')
			mnuRight.Bind(wx.EVT_MENU_RANGE, self.onMenu, id=0, id2=2)
			
			self.mnuRight = mnuRight
			
			self.swWindow.Bind(wx.EVT_RIGHT_UP, self.onRightUp)
			self.sbImage.Bind(wx.EVT_RIGHT_UP, self.onRightUp)
			self.swWindow.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
			self.sbImage.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
			self.sbImage.SetFocus()
			
			self.swWindow.SetSizer(sizerScroll)
			self.tpPos = ()
		else:
			self.textCtrl = wx.TextCtrl(self, style=wx.TE_MULTILINE)
			self.textCtrl.SetFont(wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL, False))
			
	def onMenu(self, event):
		id = event.GetId()
		if id == 0: self.scaleImage(2)
		elif id == 1: self.scaleImage(0.5)
		elif id == 2: self.scaleImage(1, True)
		
	def onKeyDown(self, event):
		keyCode = event.GetKeyCode()
		if keyCode == 90: self.scaleImage(2) #Z
		elif keyCode == 88: self.scaleImage(0.5) #X
		elif keyCode == 65: self.scaleImage(1, True) #A
			
		event.Skip()
		
	def onRightUp(self, event):
		event.GetEventObject().PopupMenu(self.mnuRight)
			
	def scaleImage(self, percent, actual = False):
		if actual:
			self.sbImage.SetBitmap(self.bmp)
			self.SetLabel(self.title)
		else:
			img = self.bmp.ConvertToImage()
			oldSize = self.sbImage.GetBitmap().GetSize()
			newSize = (float(oldSize[0]) * float(percent), float(oldSize[1]) * float(percent))
			intTest = int(newSize[0])
			intActual = self.bmp.GetSize()[0]
			if intTest < (intActual * 90) and intTest > (float(intActual) * float(0.04)):
				intQuality = 0
				if percent < 1 and intTest < intActual: intQuality = 1
				img = img.Scale(int(newSize[0]), int(newSize[1]), intQuality)
				self.SetLabel(self.title + ' (' + str(float(newSize[0]) / float(intActual) * 100) + '%)')
				self.sbImage.SetBitmap(wx.BitmapFromImage(img))
			
		self.sbImage.Fit()
		self.swWindow.FitInside()
		self.Layout()
		self.Refresh()
			
	def onSbImageMouse(self, event):
		pos = event.GetPosition()
		if event.LeftUp(): self.tpPos = ()
		
		if event.LeftIsDown():
			if self.tpPos == ():
				self.tpPos = pos
				
			tpScrollPos = self.swWindow.GetViewStart()
			self.swWindow.Scroll(tpScrollPos[0] + (self.tpPos[0] - pos[0]), \
				tpScrollPos[1] + (self.tpPos[1] - pos[1]))
				
			
	def setImage(self, bmp):
		if self.bmp:
			self.sbImage.SetBitmap(bmp)
			self.bmp = bmp
			self.title += ' (%d x %dpx)' % (self.bmp.GetWidth(), self.bmp.GetHeight())
			self.SetLabel(self.title)
			self.Show()
			
	def loadText(self, pwf):
		if not(self.bmp):
			fl = open(pwf)
			text = fl.read()
			fl.close()
			self.textCtrl.SetValue(text)
			self.Show(True)
			
	def onClose(self, event):
		wx.Frame.Destroy(self)
		event.Skip()
		
class titleLabel(wx.StaticText):
	def __init__(self, label, parent):
		wx.StaticText.__init__(self, parent=parent, style=wx.ALIGN_RIGHT, label=label)
		self.SetFont(wx.Font(wx.smallFontSize, wx.DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD, False))
		self.SetForegroundColour((102,102,102))
		
class initialTextCtrl(wx.TextCtrl):
	def __init__(self, prnt, initialText='', style=0):
		wx.TextCtrl.__init__(self, prnt, style=style)
		self.initialText = initialText
		self.setInitialText()
		self.Bind(wx.EVT_KILL_FOCUS, self.onDeactivate)
		self.Bind(wx.EVT_SET_FOCUS, self.onActivate)
		
		
	def setInitialText(self):
		self.blInitial = True
		self.SetForegroundColour((128,128,128))
		self.SetValue(self.initialText)
		
	def onActivate(self, event):
		if self.blInitial == True:
			self.SetValue('')
			self.SetForegroundColour((0,0,0))
			self.blInitial = False
			
		event.Skip()
		
	def onDeactivate(self, event):
		value = self.GetValue()
		if value == '':
			self.setInitialText()
		else:
			if value != self.initialText:
				self.blInitial = False
				
class logCtrl(wx.TextCtrl):
	def write(self, input):
		#self.Value += input
		#self.SetInsertionPoint(self.GetLastPosition() - self.GetLineLength(self.GetNumberOfLines()))
		self.AppendText(input)
		
class line(wx.Window):
	def __init__(self, prnt):
		wx.Window.__init__(self, prnt)
		self.SetSize((-1,1))
		self.SetBackgroundColour((153,153,153))
		self.prnt = prnt
		
def getInfo(frame, blLocal, pwf, sel):
		rel = frame.relativeDates
		
		if blLocal:
			tpInfo = local.getInfo(pwf)
				
			intSize = tpInfo[2]
			if tpInfo:
				date = tpInfo[3]
				strOwner = tpInfo[0]
				strGroup = tpInfo[1]
				
			strFile = sel
			
			type = local.getType(pwf)
			
			if type == 2:
				strType = 'd'
			elif type == 1:
				strType = 'l'
			else:
				strType = '-'
				
			strPerms = ''
					
		else:
			dirs = frame.dirList
			
			intSize = dirs.getSizes(pwf)
			date = dirs.getDates(pwf)
			strOwner = dirs.getOwners(pwf)
			strGroup = dirs.getGroups(pwf)
			
			strFile = dirs.getReals(pwf)
			
			strPerms = dirs.getPerms(pwf)
			strType = dirs.getType(pwf)
			
		tp = (sel, intSize, date, strOwner, strGroup, strPerms, strType, pwf)
		return tp
		
class lockedTextCtrl(wx.TextCtrl):
	def __init__(self, prnt):
		wx.TextCtrl.__init__(self, prnt, style=wx.NO_BORDER)
		self.prnt = prnt
		
		self.SetEditable(False)
		self.SetForegroundColour(prnt.GetForegroundColour())
		self.SetBackgroundColour(prnt.GetBackgroundColour())
		
class infoDialog(wx.Dialog):
	def __init__(self, prnt):
		wx.Dialog.__init__(self, prnt)
		self.prnt = prnt
		
		wrapper = wx.BoxSizer(wx.VERTICAL)
		sizerStyle = wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND
		
		arrLines = []
		for x in range(2):
			arrLines.append(line(self))
		
		sizerTop = wx.BoxSizer(wx.HORIZONTAL)
		
		self.sbIcon = wx.StaticBitmap(self)
		sizerTop.Add(self.sbIcon)
		
		#self.lblName = wx.StaticText(self, label='untitled')
		self.lblName = lockedTextCtrl(self)
		self.lblName.SetFont(wx.boldFont)
		sizerTop.Add(self.lblName, 1, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 10)
		
		wrapper.Add(sizerTop, 0, sizerStyle | wx.LEFT | wx.TOP | wx.RIGHT, 16)
		
		wrapper.Add(arrLines[0], 0, wx.EXPAND | wx.TOP, 16)
		
		sizerGrid = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
		styleLeft = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL
		styleRight = wx.EXPAND | wx.RIGHT
		self.arrLabels = []
		self.arrTexts = []
		
		self.lblWhere = titleLabel('Where', self)
		sizerGrid.Add(self.lblWhere, 0, styleLeft)
			
		self.stWhere = lockedTextCtrl(self)
		sizerGrid.Add(self.stWhere, 1, styleRight)
			
		tpLabels = ('Type','','Size','Changed','Owner', 'Group')
		
		self.whereId = -1
		self.typeId = 0
		self.etcId = 1
		self.sizeId = 2
		self.dateId = 3
		self.ownerId = 4
		self.groupId = 5
		
		for x in range(len(tpLabels)):
			self.arrLabels.append(titleLabel(tpLabels[x], self))
			sizerGrid.Add(self.arrLabels[x], 0, styleLeft)
			
			self.arrTexts.append(wx.StaticText(self, label=''))
			sizerGrid.Add(self.arrTexts[x], 1, styleRight)
			
		self.arrLabels[1].Show(False)
		self.arrTexts[1].Show(False)
		
		wrapper.Add(sizerGrid, 0, sizerStyle | wx.TOP | wx.LEFT | wx.RIGHT, 16)
		
		wrapper.Add(arrLines[1], 0, wx.EXPAND | wx.TOP, 16)
		
		lblPerms = titleLabel('Permissions', self)
		wrapper.Add(lblPerms, 0, wx.TOP | wx.LEFT | wx.RIGHT, 16)
		wrapper.Add((0,0), 0, wx.TOP, 8)
		
		sizerPerms = wx.GridSizer(cols=4, hgap=5, vgap=5)
		sizerPerms.Add((0,0), 0)
		
		arrTop = ('Read', 'Write', 'Execute')
		for x in arrTop:
			lbl = wx.StaticText(self, label=x)
			sizerPerms.Add(lbl, 0, wx.ALIGN_CENTER)
			
		arrLeft = ('Owner', 'Group', 'Other')
		self.arrChecks = []
		for x in arrLeft:
			lbl = wx.StaticText(self, label=x)
			sizerPerms.Add(lbl, 0, wx.ALIGN_RIGHT)
			
			for x in range(3):
				self.arrChecks.append(wx.CheckBox(self))
				sizerPerms.Add(self.arrChecks[-1], 0, wx.ALIGN_CENTER_HORIZONTAL)
		
		wrapper.Add(sizerPerms, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.LEFT | wx.RIGHT | wx.BOTTOM, 16)
		
		self.SetSizer(wrapper)
		self.Fit()
		
		self.SetLabel('Get Info')
		
	def showDate(self, pwf):
		type = self.prnt.dirList.getType(pwf)
		if type == 1:
			pwf = self.prnt.dirList.getDest(pwf)
		
		self.prnt.mFTP.hftp.cwd(self.strPath)
		d = self.prnt.mFTP.hftp.sendcmd('MDTM ' + format.getNameFromPath(pwf))
		return d
		
	def showDateConsumer(self, delayedresult):
		try:
			result = delayedresult.get()
			if result[:3] == '213': result = result[4:]
			
			tpTime = time.strptime(result, '%Y%m%d%H%M%S')
			
			strFormat = '%A, %d %B %Y at %H:%M:%S'
			d = format.parseDate(tpTime, False, strFormat)
			drel = format.parseDate(tpTime, True, strFormat)
			
			self.arrTexts[self.dateId].SetLabel(d + '\n(%s)' % drel)
			self.arrTexts[self.dateId].Wrap(160)
			self.Fit()
		except: pass
		
	def showInfo(self, tpInfo, blLocal = False):
		self.strName = tpInfo[0]
		self.strPath = format.getNameFromPath(tpInfo[7], True)
		intSize = int(tpInfo[1])
		strSize = format.parseSize(intSize) + '\n(%s bytes)' % locale.format('%d', intSize, True)
		self.arrTexts[self.sizeId].SetLabel(strSize)
		
		strDate = format.parseDate(tpInfo[2], False) + '\n(%s)' % format.parseDate(tpInfo[2], True)
		self.arrTexts[self.dateId].SetLabel(strDate)
		
		if tpInfo[6] != 2 and not blLocal:
			self.prnt.mFTP.tl.addTask(self.showDate, (tpInfo[7],), self.showDateConsumer)
		
		blAccess = tpInfo[3] != ''
		
		for x in range(4,6):
			self.arrLabels[x].Show(blAccess)
			self.arrTexts[x].Show(blAccess)

		if blAccess:
			self.arrTexts[self.ownerId].SetLabel(tpInfo[3])
			self.arrTexts[self.groupId].SetLabel(tpInfo[4])
			
			perms = tpInfo[5][1:]
			if perms != '':
				for x in range(3):
					sl = x * 3
					for y in range(3):
						idx = x * 3 + y
						self.arrChecks[idx].SetValue(not(perms[idx] == '-'))
			
		#self.lblName.Label = str(tpInfo[0])
		self.lblName.SetValue(self.strName)
		self.stWhere.SetValue(tpInfo[7])
		
		if tpInfo[6] == 'd' or tpInfo[6] == 2:
			bmp = self.prnt.iconPackage.iconPreFolder
		elif tpInfo[6] == 'l' or tpInfo[6] == 1:
			bmp = self.prnt.iconPackage.iconPreLink
		else:
			bmp = self.prnt.iconPackage.iconPreFile
		self.sbIcon.SetBitmap(bmp)
			
		self.Fit()